package ru.lenwp.dao;

import org.springframework.stereotype.Component;
import ru.lenwp.model.Admin;
import ru.lenwp.model.Client;
import ru.lenwp.model.User;
import ru.lenwp.util.DateUtil;
import ru.lenwp.util.DbUtil;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Lenar on 26.09.2014.
 */
@Component
public class UserDao extends AbstractDao<User> {

    public UserDao(Connection conn) {
        super(conn);
    }

    @Override
    public long insert(User entry) {
        PreparedStatement pst = null;
        Long id = DbUtil.nextId(conn, "USERS_SEQ");

        try {
            pst = conn.prepareStatement("INSERT INTO Users(login, first_name, last_name, surname, birth_date," +
                    "email, block_user, password, role_id, user_id)" +
                    "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
            initStatementWithParameters(entry, pst, id);
            entry.setId(id);
        }catch(SQLException e){
            throw new RuntimeException(e);
        }finally{
           DbUtil.close(pst);
        }
        return id;
    }

    public void initStatementWithParameters(User entry, PreparedStatement pst, Long id) throws SQLException {
        pst.setString(1, entry.getLogin());
        pst.setString(2, entry.getFirstName());
        pst.setString(3, entry.getLastName());
        pst.setString(4, entry.getSurName());
        pst.setDate(5, DateUtil.toSqlDate(entry.getDate()));
        pst.setString(6, entry.getEmail());
        pst.setString(7, entry.isBlockUser() ? "Y" : "N");
        pst.setString(8, entry.getPassword());
        pst.setLong(9, entry instanceof Admin ? 1 : 2);
        pst.setLong(10, id);
        pst.execute();
    }

    @Override
    public void update(User entry) {
        if(entry == null || entry.getId() == null){
            throw new RuntimeException("User is not found");
        }
        PreparedStatement pst = null;
        try {
            pst = conn.prepareStatement("UPDATE users SET login=?, first_name=?, last_name=?, surname=?," +
                    "birth_date=?, email=?, block_user=?, password=?, role_id=? WHERE user_id=?");
            initStatementWithParameters(entry, pst, entry.getId());
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            DbUtil.close(pst);
        }
    }

    @Override
    public User findById(long id) {
        Statement st = null;
        ResultSet rs = null;
        User user = null;
        try {
            st = conn.createStatement();
            rs = st.executeQuery("select * from users where user_id=" + id);
            if(!rs.next()){
                return null;
            }
            user = getUser(rs);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            DbUtil.close(st, rs);
        }
        return user;
    }

    public User getUser(ResultSet rs) throws SQLException {
        User user;
        Long roleId = rs.getLong("ROLE_ID");
        user = roleId == 1 ? new Admin() : new Client();
        user.setLogin(rs.getString("LOGIN"));
        user.setFirstName(rs.getString("FIRST_NAME"));
        user.setLastName(rs.getString("LAST_NAME"));
        user.setSurName(rs.getString("SURNAME"));
        user.setDate(DateUtil.toUtilDate(rs.getDate("BIRTH_DATE")));
        user.setEmail(rs.getString("EMAIL"));
        user.setBlockUser("Y".equals(rs.getString("BLOCK_USER")));
        user.setId(rs.getLong("USER_ID"));
        return user;
    }

    @Override
    public void delete(User entry) {
        Statement st = null;
        try {
            st = conn.createStatement();
            st.execute("DELETE FROM users WHERE user_id=" + entry.getId());
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            DbUtil.close(st);
        }
    }

    public List<User> allUser(){
        Statement st = null;
        ResultSet rs = null;
        List<User> res = new ArrayList<User>();
        try {
            st = conn.createStatement();
            rs = st.executeQuery("SELECT * FROM users ORDER BY user_id");
            while(rs.next()){
                res.add(getUser(rs));
            }
        } catch (SQLException e) {
            e.printStackTrace();
            return new ArrayList<User>();
        }finally {
            DbUtil.close(st, rs);
        }
        return res;
    }

    public String getPassword(String login){
        PreparedStatement pst = null;
        ResultSet rs = null;

        try {
            pst = conn.prepareStatement("SELECT password FROM users WHERE login=?");
            pst.setString(1, login);
            rs = pst.executeQuery();
            if(rs.next()){
                return rs.getString(1);
            }
            return null;
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }finally {
            DbUtil.close(pst, rs);
        }
    }

    public User getUser(String login){
        PreparedStatement pst = null;
        ResultSet rs = null;
        User user = null;
        try {
            pst = conn.prepareStatement("SELECT * FROM users WHERE login=?");
            pst.setString(1, login);
            rs = pst.executeQuery();
            if(!rs.next()){
                return null;
            }
            user = getUser(rs);
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }finally {
            DbUtil.close(pst, rs);
        }
        return user;
    }
}
